#pragma once
#include <memory>
#include <iostream>
#include <unordered_map>
#include "Connection.hpp"
#include "Epoller.hpp"
#include "../logsystem/logger/log.h"
using namespace EpollerModule;
const int gmaxevent = 32;
#define BLOCK -1

// 主要负责事件的派发&&组成
class TcpServer
{
public:
    TcpServer()
        : _stop(true), _timeout(BLOCK), _epoller(std::make_unique<Epoller>())
    {
        _epoller->InitEpoll();
    }
    bool IsConnctionExists(int sockfd)
    {
        return _connections.count(sockfd);
    }

    void LoopOnce(int timeout)
    {
        int n = _epoller->EpollWait(_revent, gmaxevent, timeout);
        // 异常处理交给read 和 send处理
        for (int i = 0; i < n; i++)
        {
            int sockfd = _revent[i].data.fd;
            uint32_t evevnt = _revent[i].events;
            // 将异常归为读写
            if (evevnt & EPOLLERR)
                evevnt |= (EPOLLIN | EPOLLOUT);
            if (evevnt & EPOLLHUP)
                evevnt |= (EPOLLIN | EPOLLOUT);
            // 到这里就该处理读事件和写事件
            if (evevnt & EPOLLIN && IsConnctionExists(sockfd))
            {
                if (_connections[sockfd]->_recver)
                    _connections[sockfd]->_recver(_connections[sockfd]);
            }
            if (evevnt & EPOLLOUT && IsConnctionExists(sockfd))
            {
                if (_connections[sockfd]->_sender)
                    _connections[sockfd]->_sender(_connections[sockfd]);
            }
        }
    }

    void EnableReadWirte(int sockfd, bool reader, bool sender)
    {
        if (!IsConnctionExists(sockfd))
            return;
        uint32_t event = EPOLLET;
        if (reader)
            event |= EPOLLIN;
        if (sender)
            event |= EPOLLOUT;
        // 修改conn关心的事件,更新到epoll中
        _connections[sockfd]->SetEvent(event);
        _epoller->ModEvent(sockfd, event);
        ILOG("开启%d号文件的(读%d:写%d)事件", sockfd, reader, sender);
    }
    void AddConnection(ConnectionPtr conn)
    {
        if (!conn.get())
            return;
        // 判断是否存在
        int sockfd = conn->GetSockfd();
        if (IsConnctionExists(sockfd))
        {
            DLOG("存在当前连接,当前文件描述符是%d", sockfd);
            return;
        }

        // 1.添加到conn中
        _connections.insert(std::make_pair(sockfd, conn));
        // 2.添加到epoll中
        _epoller->AddEvent(sockfd, conn->GetEvent());
        ILOG("添加%d号文件描述符进入新连接,并且添加到epoll...", sockfd);
    }

    void DelConnection(int sockfd)
    {
        if (!IsConnctionExists(sockfd))
            return;
        _connections[sockfd]->SetEvent(0);
        _epoller->DeletEvent(sockfd);
        // 删除map的管理
        _connections.erase(sockfd);
    }

    void Dispatcher()
    {
        _stop = false;
        int timeout = _timeout;
        while (!_stop)
        {
            _epoller->DebugFdList();
            LoopOnce(timeout);
        }
        _stop = true;
    }
    ~TcpServer()
    {
    }

private:
    int _stop;
    int _timeout;
    std::unordered_map<int, ConnectionPtr> _connections; // 用于管理连接
    struct epoll_event _revent[gmaxevent];
    std::unique_ptr<Epoller> _epoller;
};